/*
 * Copyright (C) 2010-2011 Comcast Cable.  All Rights Reserved.
 */
package com.hercules.android.receiver.handlers.events.listener;

import android.view.View;
import android.view.View.OnFocusChangeListener;

import com.hercules.android.receiver.AndroidReceiver;
import com.hercules.android.receiver.LogUtil;
import com.hercules.android.receiver.handlers.events.EventRaiser;
import com.hercules.android.receiver.handlers.events.EventRaisingException;
import com.hercules.android.receiver.handlers.events.EventsUtil;
import com.hercules.android.receiver.model.events.XREActivateViewEvent;
import com.hercules.android.receiver.model.events.XREEventPhase;
import com.hercules.android.receiver.model.objects.XREObject;

import java.util.logging.Logger;

/**
 * <p>
 * This is the listener that converts an Android focus change event to a XREActivateViewEvent, then raise it with
 * EventRaiser. It only reacts to the event whose type is given by super.eventType.
 * </p>
 *
 * <p>
 * <strong>Thread safety: </strong> This class is thread-safe because the base class is thread-safe and the class is
 * immutable.
 * </p>
 *
 * @author mekanizumu, jaindsonvs
 * @version 1.0
 */
public class ViewActivationEventListener extends BaseListener implements OnFocusChangeListener {
    /**
     * <p>
     * The logger used for logging.
     * </p>
     * <p>
     * Initialization and Mutability: It is final and won't change once it is initialized as part of variable
     * declaration to: Logger.getLogger(ViewActivationEventListener.class.getName()).
     * </p>
     * <p>
     * Usage: It's is used in all public methods.
     * </p>
     */
    private static final Logger LOGGER = Logger.getLogger(ViewActivationEventListener.class.getName());

    /**
     * <p>
     * Create an instance of the class.
     * </p>
     *
     * @param eventRaiser
     *            the EventRaiser used to raise a XRE event.
     * @param source
     *            the source of the event.
     * @param receiver
     *            the receiver that will be passed to Android listeners of this component.
     * @param eventType
     *            the event type that the listener will react to.
     * @throws IllegalArgumentException
     *             if receiver doesn't conform to the following legal value specification: It cannot be null. Or source
     *             doesn't conform to the following legal value specification: It cannot be null. Or eventType doesn't
     *             conform to the following legal value specification: It cannot be null or empty. Or eventRaiser
     *             doesn't conform to the following legal value specification: It cannot be null.
     */
    public ViewActivationEventListener(AndroidReceiver receiver, XREObject source, String eventType,
            EventRaiser eventRaiser) {
        super(receiver, source, eventType, eventRaiser);
    }

    /**
     * <p>
     * This method is called when the focus state of a view has changed.
     * </p>
     *
     * @param v
     *            the view whose state has changed.
     * @param hasFocus
     *            the new focus state of v.
     * @throws IllegalArgumentException
     *             if v is null;
     */
    public void onFocusChange(View v, boolean hasFocus) {

        final String methodName = "onFocusChange(View, boolean)";

        LogUtil.enter(LOGGER, this, methodName);

        try {
            EventsUtil.checkArgumentNull(v, "v");
        } catch (IllegalArgumentException e) {
            throw LogUtil.error(LOGGER, this, methodName, e);
        }

        //Check if event type this instance handles is one of the expected ones.
        if (!XREActivateViewEvent.ON_ACTIVATE_EVENT_NAME.equals(getEventType())
                && !XREActivateViewEvent.ON_DEACTIVATE_EVENT_NAME.equals(getEventType())) {
            LogUtil.exit(LOGGER, this, methodName);
            return;
        }

        //Check if the event type this instance handles and the new focus state match.
        if (XREActivateViewEvent.ON_ACTIVATE_EVENT_NAME.equals(getEventType()) && !hasFocus) {
            LogUtil.exit(LOGGER, this, methodName);
            return;
        }

        //Check if the event type this instance handles and the new focus state match.
        if (XREActivateViewEvent.ON_DEACTIVATE_EVENT_NAME.equals(getEventType()) && hasFocus) {
            LogUtil.exit(LOGGER, this, methodName);
            return;
        }

        XREActivateViewEvent xreEvent = new XREActivateViewEvent();

        // This block sets the properties of the event
        xreEvent.setPhase(XREEventPhase.STANDARD);
        xreEvent.setSource(getSource().getId());
        xreEvent.setTimestamp(System.currentTimeMillis());
        xreEvent.setName(getEventType());
        setNextEventIndex(xreEvent);

        EventRaiser eventRaiser = getEventRaiser();
        try {
            eventRaiser.raiseEvent(xreEvent, getReceiver(), false);
        } catch (EventRaisingException e) {
            LogUtil.error(LOGGER, this, methodName, e);
        }

        LogUtil.exit(LOGGER, this, methodName);

    }
}
